#!/usr/bin/env python

# ------------------------------------------------------------
# ::                                                WIGA-SOFT                                             ::
# ------------------------------------------------------------
# department.py
# Module for department reports
# Created by: Gedas, Wiktor
# Version: 1.0
# ------------------------------------------------------------

from __future__ import division
from pao.models import Project, Employee, Task, Department, Budget
from pao.reports.project import addMonth
from django.db.models import *
from datetime import *
from department import *

def enterpriseManagerReport(start=None, end=None):
    """
    Input:  StartPeriod? (start), EndPeriod? (end) 
    Output: Zodynas (Dictionary) 
    [
       {'department': <Skyriaus pavadinimas/numeris>,
        'departmentId': <Skyriaus numeris>
        'total': <Viso skyriaus darbuotoju isdirbta projektuose>,
        'local': <Kiek laiko skyriaus darbuotojai skyre savo skyriaus projektams>,
        'foreign': <Kiek laiko skyriaus darbuotojai skyre kitu skyriu projektams>,
        'others': { <Skyriaus numeris>: <Kiek kitas skyrius isdirbo prie sio skyriaus projektu>, ....... }
        'freetime': <Kiek laiko skyriaus darbuotojai nedirbo jokiame projekte>,
        'freepercent': <Kiek procentu laisvas laikas sudaro nuo viso (teorinio) valandu skaiciaus>}
    ]
    """
    list = []
    departments = Department.objects.all().values("id")
    for dep in departments:
        each = [departmentManagerReport(dep["id"], start, end)]
        list += each
    return list
    
def enterpriseProjectsReport(start=None, end=None):
    """
    Modulis: pao/reports/enterprise.py 
    Funkcija: enterpriseProjectsReport(start=None, end=None) 
    Input: StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries) 
    [
       {'project': <Projekto pavadinimas/kodas>, 
        'projectId': <Projekto kodas>
        'manager': <Projekto vadovas>,
        'department': <Projekto vadovo skyrius>,
        'departmentId': <Projekto vadovo skyriaus numeris>,   
        'started': <Kada projektas prasidejo>,
        'finished': <Kada projektas baigesi>,
        'local': <Kiek projekte isdirbo sio skyriaus dalyviai>,
        'foreign': <Kiek projekte isdirbo kitu skyriu dalyviai>,
        'total': <Kiek projekte isdirbo visi dalyviai>
      },
      { .... }
      { .... }
    ]
    """
    
    executableProjects = Project.objects.exclude(manager__id__username = None).values("id","name", "manager__id__username", "manager__department__id","manager__department__name").order_by("id")

    list =[]
    for project in executableProjects:
        tempStart = None
        tempEnd = None
        projectId = project["id"]
        departmentId = project["manager__department__id"]
        total = Task.objects.filter(project__id = projectId).aggregate(Min("date"),Max("date"))        
        hoursSelf = Task.objects.filter(project__manager__department__id = departmentId, employee__department__id = departmentId,project__id = projectId)
        hoursTotal = Task.objects.filter(project__manager__department__id = departmentId,project__id = projectId)
        
        
        if start != None:
            hoursSelf = hoursSelf.filter(date__gte = start)
            hoursTotal = hoursTotal.filter(date__gte = start)
        if end != None:
            hoursSelf = hoursSelf.filter(date__lte = end)
            hoursTotal = hoursTotal.filter(date__lte = end)
        
        
        hoursSelf = hoursSelf.aggregate(Sum("workhours"))
        hoursTotal = hoursTotal.aggregate(Sum("workhours"))
        projectName = project["name"]
        departmentName = project["manager__department__name"]
        if hoursTotal["workhours__sum"] == None:
            hoursT = 0
        else:
            hoursT = hoursTotal["workhours__sum"]
        if hoursSelf["workhours__sum"] == None:
            hoursS = 0
        else:
            hoursS = hoursSelf["workhours__sum"]
        foreign = hoursT - hoursS
        
        addToList = True       
        if start == None:
            tempStart = total["date__min"]
        else:
            tempStart = start
        if end == None:
            tempEnd = total["date__max"]
        else:
            tempEnd = end
        if ((tempStart < total["date__min"] and tempEnd < total["date__min"]) or (tempStart > total["date__max"] and tempEnd > total["date__max"])):
            addToList = False
        
        
        if addToList == True:
            list += [{"project": projectName,
                      "projectId":projectId, 
                      "manager": project["manager__id__username"],
                      "departmentId":departmentId,
                      "department": departmentName, 
                      "started": total["date__min"], 
                      "finished": total["date__max"],
                      "local": hoursS, 
                      "foreign": foreign , 
                      "total": hoursT}]
    
    return list
def enterpriseBudgetReport(start=None, end=None):
    """
    Input: DepartmentID (department), StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries)
    
    [
        {'date': <Metai-Menuo>,
        'total': <Kiek biudzeto skirta>,
        'used': <Kiek biudzeto isnaudota>,
        'left': <Kiek biudzeto liko>,
        'percent': <Likutis procentais> },
        { .... },
        { .... }
    ]
    """
    
    workhours = Task.objects.all()
    budget = Budget.objects.all()
    if start != None:
        workhours = workhours.filter(date__gte = start)
        budget = budget.filter(date__gte = start)
        
    if end != None:
        workhours = workhours.filter(date__lte = end)
        budget = budget.filter(date__lte = end)
        
    whDate = workhours.aggregate(Min("date"),Max("date"))   
    bdDate = budget.aggregate(Min("date"),Max("date"))   
    
    if whDate["date__min"] == None:
        whDate = bdDate
    if bdDate["date__min"] == None:
        bdDate = whDate
    if bdDate["date__min"] == None:
        return []
    if whDate["date__min"] > bdDate["date__min"]:
        start = bdDate["date__min"]
    else:
        start = whDate["date__min"]
    if whDate["date__max"] < bdDate["date__max"]:
        end = bdDate["date__max"]
    else:
        end = whDate["date__max"]  
    
    workhours = workhours.values("date").annotate(Sum("workhours"))
    budget = budget.values("date").annotate(Sum("workhours"))
    if date.today().year % 4 == 0:
        year = timedelta(days=366)
    else:
        year = timedelta(days=365)
    dif_month = (end.year - start.year) * 12 - end.month + start.month
    list = []
    
    while start <= end:
        bdg = {"workhours__sum": 0}
        for bd in budget:
            if bd["date"] == start:
                bdg = bd
        
        who = {"workhours__sum": 0}
        for wh in workhours:
            if start == wh["date"]:
                who = wh
        if who["workhours__sum"] == None:
            who["workhours__sum"] = 0
        if bdg["workhours__sum"] == None:
            bdg["workhours__sum"] = 0
        if bdg["workhours__sum"] == 0: 
            percent = None
        else:
            percent = 100 - (100 * who["workhours__sum"] / bdg["workhours__sum"])
        list += [{"date": start,
                  "total": bdg["workhours__sum"],
                  "used": who["workhours__sum"],
                  "left": bdg["workhours__sum"] - who["workhours__sum"],
                  "percent": percent}]
        start = add_months(start)
    
    return list
    
def add_months(input, months = 1):

    year, month, day = input.timetuple()[:3]
    new_month = month + months
    
    return date(year + int((new_month - 1) / 12), (new_month - 1) % 12 + 1, day)

def enterpriseEmployeeLoadReport(start=None, end=None):
    """
    Input: StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries)
    [
      {'date': <Metai-Menuo>,
       'workers': <Darbuotoju skaicius ta menesi visoje firmoje>,
       'resource': <Max. valandos - resursas (Darbuotoju skaicius x 160)>,
       'budget': <Biudzetas skirtas siam laikotarpiui visoje firmoje>,
       'percent': <Kokia dalis resoursu padengta biudzetu>},
      { ... }
    ]
    """
    
    if start is None:
        start = date(1990, 1, 1)
    if end is None:
        end = date.today()
    result = []
    departmentTasks = Task.objects.all()
    departmentTasks = departmentTasks.filter(date__gte = start)
    departmentTasks = departmentTasks.filter(date__lte = end)
    dates = []
    for e in departmentTasks:
        if e.date not in dates:
            if e.date >= start:
                if e.date <= end:
                    dates.append(e.date)
    dates.sort()
    if len(dates) > 0:
        e = min(dates)
        endDate = max(dates)
        while e <= endDate:
            tmpDepartmentTasks = departmentTasks.filter(date = e)
            workers = []
            workhours = 0
            for i in tmpDepartmentTasks:
                if i.employee not in workers:
                    workers.append(i.employee)
            tmpBudget = Budget.objects.filter(date = e)
            for i in tmpBudget:
                workhours += i.workhours
            tmpRez = {}
            workerCount = len(workers)
            tmpRez['date'] = e
            tmpRez['workers'] = workerCount
            tmpRez['resource'] = workerCount * 160
            tmpRez['budget'] = workhours
            if workerCount != 0:
                tmpRez['percent'] = (workhours * 100) / (workerCount * 160)
            else:
                tmpRez['percent'] = None
            result.append(tmpRez)
            e = addMonth(e)
    return result  
    
def enterpriseUnexecutedProjectsReport():
    allProjects = Project.objects.all()
    allProjects = allProjects.filter(manager = None)
    result = []
    for e in allProjects:
        tmp = {}
        tmp['projectId'] = e.id
        tmp['project'] = e.name
        result.append(tmp)
    return result